package net.yxsoft;

import com.alibaba.druid.filter.logging.Log4jFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.*;

import com.jfinal.core.JFinal;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;

import com.jfinal.plugin.cron4j.Cron4jPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;
import com.jfinal.template.source.ClassPathSourceFactory;

import lombok.SneakyThrows;
import net.dreamlu.event.EventPlugin;
import net.yxsoft.chainmaker.InitClient;
import net.yxsoft.chainmaker.Subscribe;
import net.yxsoft.controller.common.*;
import net.yxsoft.controller.common.interceptor.GlobalExceptionInterceptor;
import net.yxsoft.controller.common.interceptor.GlobalInterceptor;


import net.yxsoft.controller.pc.consumer.common.PCConsumerRoutes;
import net.yxsoft.controller.pc.sysmgt.common.PCSysMgtRoutes;
import net.yxsoft.controller.pc.sysmgt.infrastructure.PCSysMgtBaseRoutes;
import net.yxsoft.handler.XssHandler;
import net.yxsoft.kit.SplitDirective;

import net.yxsoft.message.plugin.MessagePlugin;

import net.yxsoft.model._MappingKit;
import net.yxsoft.model.formdesigner._FormDesignerMappingKit;
import net.yxsoft.model.infrastructure._InfrastructureMappingKit;


import net.yxsoft.quorum.QuorumPlugin;
import net.yxsoft.resource.DbSourceRes;
import net.yxsoft.resource.PathRes;
import net.yxsoft.service.BlockchainManagementService;
import net.yxsoft.service.EvidenceService;
import net.yxsoft.service.OrderService;
import net.yxsoft.service.infrastructure.SystemService;
import net.yxsoft.swagger.config.SwaggerConfig;
import net.yxsoft.swagger.config.SwaggerRoute;
import net.yxsoft.swagger.enums.InType;
import net.yxsoft.websocket.NettyForJFinalPlugin;

import rapid.jfinal.ApplicationBaseJFinalConfig;

import rapid.util.DruidKit;

import java.sql.Connection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static net.yxsoft.chainmaker.InitClient.inItChainClient;


public class ApplicationGlobalConfig extends ApplicationBaseJFinalConfig {
    //  private WallFilter wallFilterOra;

    public ApplicationGlobalConfig() {
        super("yx");

        // web资源文件的版本号配置，如果设置为false，则读取的是init.properties中的版本号
        this.webResourceConfig.setRandomVersion(false);
    }

    /**
     * 启动入口，运行此 main 方法可以启动项目，此main方法可以放置在任意的Class类定义中，不一定要放于此
     * 使用本方法启动过第一次以后，会在开发工具的 debug、run configuration 中自动生成
     * 一条启动配置项，可对该自动生成的配置再继续添加更多的配置项，例如 VM argument 可配置为：
     * -XX:PermSize=64M -XX:MaxPermSize=256M
     * 上述 VM 配置可以缓解热加载功能出现的异常
     */
    public static void main(String[] args) {
        //    JFinal.start("src/main/webapp", initProp.getInt("port"), "/");

        UndertowServer.start(ApplicationGlobalConfig.class);


    }

    /**
     * 配置模板
     */
    @Override
    public void configEngine(Engine me) {
        super.configEngine(me);

        String commPath = "/shared";
        String masterPath = commPath + "/master.html";


        // 页面布局
        me.addSharedFunction(PathRes.PATH_PC_MGT_VIEW + masterPath);
        // 脚本布局
        me.addSharedFunction(PathRes.PATH_PC_MGT_VIEW + commPath + "/master_js.html");

        me.addDirective("strsplit", SplitDirective.class);

    }

    @Override
    public void configRoute(Routes me) {

        me.add(PathRes.URL_NOTIFY, NotifyController.class);
        me.add(PathRes.URL_COMM_API, ApiController.class);


        me.add(new PCSysMgtBaseRoutes());

        me.add(new PCSysMgtRoutes());


        me.add(new PCConsumerRoutes());


        // 如果在微信端要做类似PC端的管理系统，就注册me.add(new MobileSysMgtRoutes());


        // 配置Swagger UI访问路由
        me.add(new SwaggerRoute());
    }

    @Override
    public void configConstant(Constants me) {
        super.configConstant(me);
        /**
         * 加入DuBBO的Reference注释否则@ReferenceService注解获取不到service(在Controller中用时需添加此项)
         */

        //最大上传500M
        me.setMaxPostSize(1024 * 1024 * 500);
        me.setBaseUploadPath(PathRes.PATH_BASE_UPLOAD);
        me.setBaseDownloadPath(PathRes.PATH_BASE_DOWNLOAD);

        me.setInjectDependency(true);

    }

    /**
     * 抽取成独立的方法，例于 _ModelGenerator 中重用该方法，减少代码冗余
     */
    public static DruidPlugin getDruidPlugin() {
        return new DruidPlugin(initProp.get("jdbcUrl"), initProp.get("user"), initProp.get("password").trim());
    }

    @Override
    public void configPlugin(Plugins me) {
        //region 系统主数据源
        DruidPlugin druidPlugin = getDruidPlugin();
        WallFilter wallFilter = new WallFilter();              // 加强数据库安全

        wallFilter.setDbType(DbSourceRes.DB_SOURCE);
        Log4jFilter logFilter = new Log4jFilter();
        logFilter.setStatementLogEnabled(false);
        logFilter.setStatementLogErrorEnabled(true);
        logFilter.setStatementExecutableSqlLogEnable(true);

        druidPlugin.addFilter(wallFilter);
        druidPlugin.addFilter(new StatFilter());    // 添加 StatFilter 才会有统计数据
        druidPlugin.addFilter(logFilter);  //打印SQL

        druidPlugin.setRemoveAbandoned(true);//超过时间限制回收连接
        druidPlugin.setRemoveAbandonedTimeoutMillis(180000L);//超时时间，单位未毫秒
        druidPlugin.setLogAbandoned(true);//关闭abndoned连接时输出错误日志

        me.add(druidPlugin);

        // 系统主数据源
        ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
        arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);

        arp.setContainerFactory(new CaseInsensitiveContainerFactory(true));
        arp.setDialect(new MysqlDialect());


        if (initProp.getBoolean("devMode", false)) {
            arp.setShowSql(true);
        }

        arp.getEngine().setSourceFactory(new ClassPathSourceFactory());
        arp.addSqlTemplate("all_sqls.sql");

        _FormDesignerMappingKit.mapping(arp);
        _InfrastructureMappingKit.mapping(arp);
        _MappingKit.mapping(arp);

        me.add(arp);
        //endregion


        me.add(new NettyForJFinalPlugin());
        me.add(new EhCachePlugin());
        me.add(new MessagePlugin());
        me.add(new QuorumPlugin(initProp));
        me.add(new Cron4jPlugin(initProp));


        EventPlugin eventPlugin = new EventPlugin();

        eventPlugin.async();


        if (JFinal.me().getConstants().getDevMode()) {
            eventPlugin.scanJar().scanPackage("net.yxsoft.event");
        }

        me.add(eventPlugin);
    }

    @Override
    public void configInterceptor(Interceptors me) {
        // 全局拦截器
        me.add(new GlobalInterceptor());
        me.add(new GlobalExceptionInterceptor()); // 添加全局异常拦截器

    }

    public void configHandler(Handlers me) {
        me.add(DruidKit.getDruidStatViewHandler()); // druid 统计页面功能

        me.add(new XssHandler(""));
    }

    @SneakyThrows
    @Override
    public void onStart() {
        super.onStart();

        SystemService.start();

        //链初始化
        try {
            inItChainClient();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


        //配置添加全局参数(如token，非必需)
        SwaggerConfig.addGlobalParam("sign", "签名", "string", "", true, "", InType.HEADER);
        SwaggerConfig.addGlobalParam("appId", "AppId", "string", "", true, "", InType.HEADER);
        SwaggerConfig.addGlobalParam("timestamp", "时间戳", "long", "", true, "", InType.HEADER);

        ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);

        // 定时杀死并重启同步链上线程的任务
        Runnable restartTask = () -> {

            //取所有智能合约信息
            List<Record> records = Db.find("SELECT distinct attrib_06, attrib_33 FROM fn_form_data WHERE ATTRIB_01='8a43bd9e876449af9e4c98587a24dc53' ");

            ExecutorService executor = Executors.newFixedThreadPool(records.size());
            for (int i = 0; i < records.size(); i++) {
                String scontactname = records.get(i).get("attrib_06");
                String sTopic = records.get(i).get("attrib_33");

                // 创建并启动线程
                Thread thread = new Thread(new Subscribe(scontactname, sTopic));
                executor.submit(thread);

                System.out.println("\n开始订阅合约信息: " + scontactname + " " + sTopic);

            }
        };

        // 提交定时任务，每隔一定时间（例如5秒）执行一次任务
        scheduledExecutor.scheduleAtFixedRate(restartTask, 0, 1, TimeUnit.DAYS);

//        以下为测试代码
//        EvidenceService.getAllEvidencesToDb(InitClient.chainClient,"evidence619");
//        OrderService.getAllOrdersToDb(InitClient.chainClient, "sharedata611");
//        OrderService.getAllStatesToDb(InitClient.chainClient,"sharedata611");
//        OrderService.getLatestBlock(InitClient.chainClient);
//        BlockchainManagementService blockchainManagementService = new BlockchainManagementService();
//        blockchainManagementService.getLatestTime(InitClient.chainClient);

    }

}
